home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
lisp
/
eulisp
/
feel0_89.lha
/
Feel
/
Modules
/
defs.em
< prev
next >
Wrap
Lisp/Scheme
|
1993-07-15
|
12KB
|
406 lines
;; Eulisp Module
;; Author: pab
;; File: defs.em
;; Date: Fri Jun 12 18:01:37 1992
;;
;; Project:
;; Description:
;;
(defmodule defs
( macros0
(except (not) extras0)
(except (not) init)
)
()
(defun not (x) (null x))
;; XXX: Boot problemette
;; 'defstruct'...
;; Utils...
(defconstant *key-list-fail* nil)
;;(defun not (x) (null x))
(defconstant *nothing* (gensym))
(defun search-key-list (l k)
(cond ((null l) *key-list-fail*)
((eqcar l k) (cadr l))
(t (search-key-list (cddr l) k))))
(defconstant invalid-slot-options nil)
'(make <condition-class>
'name 'invalid-slot-options
'direct-superclasses (list <condition>)
'direct-slot-descriptions
`((name options
initargs (options)
initform ,(lambda () ())
slot-class ,local-slot-description)))
(deflocal *name* nil)
(deflocal *readers* nil)
(deflocal *writers* nil)
(deflocal *accessors* nil)
(deflocal *initargs* nil)
(defun reset ()
(setq *name* nil)
(setq *readers* nil)
(setq *writers* nil)
(setq *accessors* nil)
(setq *initargs* nil))
(defun canonicalise (ops def-slot-class)
(when (symbolp ops) (setq ops (list ops)))
(unless (consp ops) (error "slot options not a list"
<Internal-Error> 'options ops))
(let ((name *nothing*)
(slot-class def-slot-class)
(slot-initargs *nothing*)
(initform *nothing*)
(initarg nil)
(readers nil)
(writers nil)
(accessors nil))
(labels
((inner (l)
(unless (null l)
(let ((key (car l))
(val (cadr l)))
(cond ((eq key 'initarg)
(setq initarg (list val)))
((eq key 'initform)
(if (eq initform *nothing*)
(setq initform `(lambda () ,val))
(error "bad initform"
invalid-slot-options 'options ops)))
((eq key 'initfunction)
(if (eq initform *nothing*)
(setq initform val)
(error "Initform multiply defined"
invalid-slot-options
'options ops)))
((eq key 'slot-class)
(if (eq slot-class def-slot-class)
(setq slot-class val);;do find-dbclass of val
(error "slot-class multiply defined"
invalid-slot-options 'options ops)))
((eq key 'slot-initargs)
(if (eq slot-initargs *nothing*)
(setq slot-initargs val);; was class-initargs
(error "slot initargs multiply defined"
invalid-slot-options 'options ops)))
((eq key 'reader)
(setq readers (cons (cons val name) readers)))
((eq key 'writer)
(setq writers (cons (cons val name) writers)))
((eq key 'accessor)
(setq accessors (cons (cons val name) accessors)))
(t (error "unknown slot option"
invalid-slot-options 'options ops))))
(inner (cddr l)))))
(setq name (car ops))
(inner (cdr ops))
(setq *readers* (nconc readers *readers*))
(setq *writers* (nconc writers *writers*))
(setq *accessors* (nconc accessors *accessors*))
(setq *initargs* (nconc initarg *initargs*))
(when (eq slot-class *nothing*)
(setq slot-class '<local-slot-description>))
(when (eq slot-initargs *nothing*)
(setq slot-initargs nil))
(nconc `(list 'name ',name
,@(if slot-class `('slot-class ,slot-class ) nil)
,@slot-initargs
,@(if initarg `('initarg ',(car initarg)) ()))
(if (eq initform *nothing*)
`('initfunction ',unbound-slot-value)
`('initfunction ,initform))))))
(defun reader-defs (o)
(mapcar
(lambda (pair)
`(defconstant ,(car pair) (find-slot-reader ,*name* ',(cdr pair))))
*readers*))
(defun writer-defs (o)
(mapcar
(lambda (pair)
`(defconstant ,(car pair) (find-slot-writer ,*name* ',(cdr pair))))
*writers*))
(defun accessor-defs (o)
(mapcar
(lambda (pair)
`(progn
(defconstant ,(car pair) (find-slot-reader ,*name* ',(cdr pair)))
((setter setter) ,(car pair) (find-slot-writer ,*name* ',(cdr pair)))))
*accessors*))
(defun make-constructor-initarg-list (ll)
(if (not (consp ll)) ()
(cons (list 'quote (car ll))
(cons (car ll) (make-constructor-initarg-list (cdr ll))))))
(defun improper-list-p (l)
(if (null (consp l)) l (improper-list-p (cdr l))))
(defun make-positional-constructor-def (spec)
(let* ((name (car spec))
(ll (cdr spec))
(tail (improper-list-p ll)))
(if (null tail)
`(defun ,name ,ll
(make ,*name*
,@(make-constructor-initarg-list ll)))
`(defun ,name ,ll
(apply
make
,*name*
(nconc (list ,@(make-constructor-initarg-list ll)) ,tail))))))
(defun constructor-defs (o)
(cond ((null o) nil)
((null (cdr o)) (error "unbalance class ops"
invalid-slot-options 'options o))
((eqcar o 'constructor)
(let ((spec (car (cdr o))))
(if (atom spec)
(cons (make-positional-constructor-def (cons spec 'args))
(constructor-defs (cddr o)))
(cons (make-positional-constructor-def spec)
(constructor-defs (cddr o))))))
((eqcar o 'predicate)
(cons `(progn
(defgeneric ,(car (cdr o)) (obj))
(defmethod ,(car (cdr o)) ((obj <object>)) ())
(defmethod ,(car (cdr o)) ((obj ,*name*)) obj))
(constructor-defs (cddr o))))
(t (constructor-defs (cddr o)))))
(defun quotify-alternate (l)
(if (null l) ()
(cons (list 'quote (car l))
(cons (car (cdr l))
(quotify-alternate (cdr (cdr l)))))))
(defun metaclass-initargs (ops)
(let ((args (search-key-list ops 'metaclass-initargs)))
(unless (eq args *key-list-fail*)
(quotify-alternate args))))
(defmacro defstruct (name super slot-ops . class-ops)
(reset)
(setq *name* name)
`(progn
(defconstant ,name
(make <structure-class>
'name ',name
'direct-superclasses ,(if super `(list ,super) '(list <structure>))
'direct-slot-descriptions
(list ,@(mapcar (lambda (x) (canonicalise x '<local-slot-description>))
slot-ops))
'metaclass-hypotheses nil))
,@(reader-defs slot-ops)
,@(writer-defs slot-ops)
,@(accessor-defs slot-ops)
,@(constructor-defs class-ops)
',name))
(export defstruct)
(defmacro defclass (name supers slot-ops . class-ops)
(reset)
(setq *name* name)
(let ((metaclass
(or (search-key-list class-ops 'metaclass) '<class>))
(initargs
(or (search-key-list class-ops 'metaclass-initargs) nil))
(additional-initargs (or (search-key-list class-ops 'direct-initargs) nil))
(slot-class (search-key-list class-ops 'default-slot-class) ))
`(progn
(defconstant ,name
(make ,metaclass
'name ',name
'direct-superclasses ,(if supers `(list ,@supers) '(list <object>))
'direct-slot-descriptions
(list ,@(mapcar (lambda (x) (canonicalise x slot-class))
slot-ops))
'metaclass-hypotheses ()
'direct-initargs ',(append additional-initargs *initargs*)
,@(metaclass-initargs class-ops)))
,@(reader-defs slot-ops)
,@(writer-defs slot-ops)
,@(accessor-defs slot-ops)
,@(constructor-defs class-ops)
',name)))
(export defclass)
(defmacro defreader (name class slot)
`(defconstant ,name (find-slot-reader ,class ',slot)))
(defmacro defwriter (name class slot)
`(defconstant ,name (find-slot-writer ,class ',slot)))
(defmacro defaccessor (name class slot)
`(progn
(defconstant ,name (find-slot-reader ,class ',slot))
((setter setter) ,name (find-slot-writer ,class ',slot))))
(defmacro defpredicate (name class)
`(progn
(defgeneric ,name (x))
(defmethod ,name ((x <object>)) ())
(defmethod ,name ((x ,class)) x)))
(export defreader defwriter defaccessor defpredicate)
(defun method-extra-args ()
(if (compile-time-p)
()
(list '***method-status-handle*** '***method-args-handle***)))
(defun sll-signature (ll)
(cond ((atom ll) nil)
((consp (car ll)) (cons (cadar ll) (sll-signature (cdr ll))))
(t (cons '<object> (sll-signature (cdr ll))))))
(defun sll-formals (ll)
(cond ((null ll) nil)
((atom ll) ll)
((consp (car ll)) (cons (caar ll) (sll-formals (cdr ll))))
(t (cons (car ll) (sll-formals (cdr ll))))))
(defun gf-class (ops)
(let ((val (search-key-list ops 'class)))
(if (eq val *key-list-fail*) '<generic-function> val)))
(defun gf-method-class (ops)
(let ((val (search-key-list ops 'method-class)))
(if (eq val *key-list-fail*) '<method> val)))
(defun gl-name (ops)
(let ((val (search-key-list ops 'name)))
(if (eq val *key-list-fail*) '*unnamed-lambda* val)))
(defun find-method-list (ops)
(labels ((grab-methods (ops so-far)
(cond ((null ops) (nreverse so-far))
((eq (car ops) 'method)
(grab-methods (cddr ops) (cons (cadr ops) so-far)))
(t (grab-methods (cddr ops) so-far)))))
(let ((meths (search-key-list ops 'methods)))
(if (eq meths *key-list-fail*)
(grab-methods ops nil)
(nconc (grab-methods ops nil) meths)))))
(defun gf-methods (ops mc)
(let ((val (find-method-list ops)))
`(list
,@(mapcar
(lambda (form)
`(make ,mc
'signature (list ,@(sll-signature (car form)))
'function
(lambda (,@(method-extra-args)
,@(sll-formals (car form)))
,@(cdr form))))
val))))
(defmacro defgeneric (name ll . ops)
`(,@(if (symbolp name) (list 'defconstant name)
(list `(setter setter) (car (cdr name))))
(make ,(gf-class ops)
'name ',name
'lambda-list ',ll
'method-class ,(gf-method-class ops)
'argtype ,(list-length ll)
'methods ,(gf-methods ops (gf-method-class ops))
'domain (list ,@(sll-signature ll))
)))
(export defgeneric)
(defmacro defmethod (name sll . body)
(defmethod-aux `(generic-method-class ,name) nil name sll body))
(defmacro defextmethod (opts name sll . body)
(let ((class (scan-args 'class opts (default-argument `(generic-method-class ,name) )))
(opts (quotify-alternate opts)))
(defmethod-aux class opts name sll body)))
(export defextmethod)
(defun defmethod-aux (class opts name sll body)
`(progn
(add-method
,name
(make ,class
'signature (list ,@(sll-signature sll))
'argtype ,(length sll)
'function
(lambda ,(append (method-extra-args)
(sll-formals sll))
,@body)
,@opts))))
(export defmethod)
(defun defcondition-slot-descriptions (l)
(if (null l) nil
(cons `(list 'name ',(car l)
'slot-class <local-slot-description>
'initargs ',(list (car l))
'initform (lambda () ,(cadr l)))
(defcondition-slot-descriptions (cddr l)))))
(defmacro defcondition (name super . pairs)
`(defconstant ,name
(make <condition-class>
'name ',name
'direct-superclasses (list ,(if super super '<condition>))
'direct-slot-descriptions
(list ,@(defcondition-slot-descriptions pairs)))))
(export defcondition)
(defmacro call-next-method ()
(if (compile-time-p)
'(call-method-by-list (method-method-list)
(method-arg-list))
'(if ***method-status-handle***
(progn ;;(format t "Call next: ~a ~a\n"
;;***method-status-handle***
;; ***method-args-handle***)
(apply call-method-by-list
(list ***method-status-handle***
***method-args-handle***)))
(error "No Next Method" <Internal-Error> nil))))
(defmacro next-method-p ()
(if (compile-time-p)
(progn (error "Next-method-p: not implemented" <Internal-Error>)
nil)
'***method-status-handle***))
(export next-method-p)
(defmacro generic-lambda (args . ops)
`(make ,(gf-class ops)
'name ',(gl-name ops)
'lambda-list ',args
'method-class ,(gf-method-class ops)
'methods ,(gf-methods ops (gf-method-class ops))))
(export call-next-method generic-lambda)
)